#include "StdAfx.h"
#include "Objective.h"
#include "Trigger.h"
#include "Operation.h"
#include "Operand.h"
#include "Condition.h"

namespace _DATAPART_
{
	namespace _GAME_
	{

		Objective::Objective(void)
		{
			m_uiPrimaryObjectuveCount=0;

			m_eObjectiveStateType = eOST_Inactive;
		}

		Objective::~Objective(void)
		{
		}
		void Objective::AddObjective(Objective* ob,bool startActive)
		{
			if(ob->GetType() == eOT_Primary )
			{
				m_uiPrimaryObjectuveCount++;
			}

			if(startActive)
			{
				m_queueActivateSubObjectives.push(ob->GetTagName());
			}

			m_InactivedSubObjectives.push_back(ob);
		}

		void Objective::Update(float elapsedtime)
		{
			std::list<Objective*>::iterator iterObj;
			std::list<Objective*>::iterator iterEnd;

			//check activate list
			while(m_queueActivateSubObjectives.size()>0)
			{
				_FO_UTIL::Name name=m_queueActivateSubObjectives.front();
				m_queueActivateSubObjectives.pop();


				//find and move to active list	
				iterObj=m_InactivedSubObjectives.begin();
				iterEnd=m_InactivedSubObjectives.end();
				for(;iterObj!=iterEnd;)
				{
					Objective* ptrObj=*iterObj;

					if(ptrObj->GetTagName() == name)
					{
						m_InactivedSubObjectives.erase(iterObj);
						m_ActivedSubObjectives.push_back(ptrObj);

						break;
					}
					else
					{
						++iterObj;
					}
				}
			}


			//check objective state
			if(m_eObjectiveStateType==eOST_Active)
			{
				//check inactive subobjectives
				iterObj=m_InactivedSubObjectives.begin();
				iterEnd=m_InactivedSubObjectives.end();
				for(;iterObj!=iterEnd;)
				{
					Objective* ptrObj=*iterObj;

					//update sub objectives to refresh acive list
					ptrObj->Update(elapsedtime);

					if(ptrObj->GetState()==eOST_Active)
					{// move inactivated objective to activedlist.
						m_InactivedSubObjectives.erase(iterObj);
						m_ActivedSubObjectives.push_back(ptrObj);
					}
					else
					{
						++iterObj;
					}
				}

				//check active subobjectives

				iterObj=m_ActivedSubObjectives.begin();
				iterEnd=m_ActivedSubObjectives.end();
				for(;iterObj!=iterEnd;)
				{
					Objective* ptrObj=*iterObj;

					//update sub objectives to check success or fail
					ptrObj->Update(elapsedtime);

					if(ptrObj->GetState()==eOST_Success)
					{// move activated objective to successlist.
						m_ActivedSubObjectives.erase(iterObj);
						m_SuccessedSubObjectives.push_back(ptrObj);
					}
					else if(ptrObj->GetState()==eOST_Fail)
					{// move activated objective to faillist.
						m_SuccessedSubObjectives.erase(iterObj);
						m_FailedSubObjectives.push_back(ptrObj);
					}
					else
					{
						++iterObj;
					}
				}

				//check fail list

				iterObj=m_FailedSubObjectives.begin();
				iterEnd=m_FailedSubObjectives.end();
				for(;iterObj!=iterEnd;++iterObj)
				{
					Objective* ptrObj=*iterObj;

					if(ptrObj->GetType()==eOT_Primary)
					{// primary object is fail. so this objective is fail too
						m_eObjectiveStateType=eOST_Fail;

						//trigger fail event
						TriggerEvent(m_nameFailTrigger,this);
						return;
					}
				}

				//check my condition
				if(	m_ptrConditionFail&&m_ptrConditionFail->Check())
				{
					//even if sub objectives are not fail, mycondition is fail.so objective is fail
					m_eObjectiveStateType=eOST_Fail;

					//trigger fail event
					TriggerEvent(m_nameFailTrigger,this);
					return;
				}


				//check success

				if(m_uiPrimaryObjectuveCount == m_SuccessedSubObjectives.size())
				{// this objective is success

					if(m_ptrConditionSuccess&&m_ptrConditionSuccess->Check())
					{
						m_eObjectiveStateType=eOST_Success;

						//trigger success event
						TriggerEvent(m_nameSuccessTrigger,this);
					}
				}
			}
		}

		/*virtual*/
		void Objective::Trigger(_P_GAME::GamePart* Instigator)
		{
			if(m_eObjectiveStateType==eOST_Inactive)
			{// change to active state
				m_eObjectiveStateType = eOST_Active;

				//trigger active event
				TriggerEvent(m_nameActiveTrigger,this);
			}
		}
	}
}